package com.chrray.position.service.auth.impl;


import com.chrray.position.entity.position.SysRole;
import com.chrray.position.entity.position.SysRoleMenu;
import com.chrray.position.enums.YesNoEnum;

import com.chrray.position.mapper.position.SysMenuMapper;
import com.chrray.position.mapper.position.SysRoleMapper;
import com.chrray.position.mapper.position.SysRoleMenuMapper;
import com.chrray.position.mapper.position.SysUserMapper;
import com.chrray.position.pojo.dto.auth.*;

import com.chrray.position.pojo.dto.util.BaseAllDto;
import com.chrray.position.service.auth.SysJurisdictionService;
import com.chrray.position.util.redis.RedisUtils;

import com.chrray.position.util.result.PageBean;
import com.chrray.position.util.result.ResponseResult;
import com.chrray.position.util.result.ResultEnum;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

import static com.chrray.position.util.result.ResponseResults.fail;
import static com.chrray.position.util.result.ResponseResults.success;


/**
 * @Author: LM
 * @Description:
 * @Date: 2021/1/8 10:05
 */
@Service
public class SysJurisdictionServiceImpl implements SysJurisdictionService {


    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private SysRoleMenuMapper roleMenuMapper;
    @Resource
    private SysMenuMapper wtMenuMapper;

    @Resource
    private SysUserMapper sysUserMapper;


    @Autowired
    private RedisUtils redisUtil;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult roleInsert(RoleInsertDto roleDto) {

        if (StringUtils.isBlank(roleDto.getRoleName())) {
            return fail(ResultEnum.MUST_PARAMETER);
        }
        SysRole role = new SysRole();
        BeanUtils.copyProperties(roleDto, role);
        sysRoleMapper.insertSelective(role);
        /*        List<SysMenuTreeDto> list = roleDto.getMenuList();
         *//**
         * 保存权限对应的按钮权限
         *//*
        addRoleMenu(list, Role.getId());*/
        return success();
    }

    public void addRoleMenu(List<SysMenuTreeDto> list, Long roleId) {
        list.forEach(
                sysMenuTreeDto -> {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setMenuId(sysMenuTreeDto.getId());
                    roleMenu.setRoleId(roleId);
                    roleMenu.setType(sysMenuTreeDto.getMenuType());
                    roleMenu.setState(sysMenuTreeDto.getState());
                    roleMenu.setFullControl(sysMenuTreeDto.getFullControl());
                    roleMenuMapper.insertSelective(roleMenu);
                    addRoleMenu(sysMenuTreeDto.getMenuList(), roleId);
                }
        );
    }

    public void addRoleMenuByUserId(List<SysMenuTreeDto> list, Long userId, Long roleId) {
        list.forEach(
                sysMenuTreeDto -> {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setMenuId(sysMenuTreeDto.getId());
                    roleMenu.setRoleId(roleId);
                    roleMenu.setUserId(userId);
                    roleMenu.setType(sysMenuTreeDto.getMenuType());
                    roleMenu.setState(sysMenuTreeDto.getState());
                    roleMenu.setFullControl(sysMenuTreeDto.getFullControl());
                    roleMenuMapper.insertSelective(roleMenu);
                    addRoleMenuByUserId(sysMenuTreeDto.getMenuList(), userId, roleId);
                }
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult roleUpdate(RoleUpdateDto roleDto) {

        if (roleDto.getId() == null) {
            return fail(ResultEnum.MUST_PARAMETER);
        }
        if (roleDto.getId().equals(1L) || roleDto.getId().equals(2L)) {
            return fail("该角色不允许修改！");
        }
        SysRole role = new SysRole();
        BeanUtils.copyProperties(roleDto, role);
        sysRoleMapper.updateByPrimaryKeySelective(role);
        /*
         *//**
         * 删除历史按钮权限
         *//*
        roleMenuMapper.delByRoleId(Role.getId());
        *//**
         * 保存权限对应的按钮权限
         *//*
        addRoleMenu(roleDto.getMenuList(), Role.getId());*/

        return success();
    }

    @Override
    public ResponseResult roleUpdateMenu(RoleDto roleDto) {

        if (roleDto.getId() == null) {
            return fail(ResultEnum.MUST_PARAMETER);
        }
        if (roleDto.getId().equals(1L) || roleDto.getId().equals(2L)) {
            return fail("该角色不允许设置权限！");
        }
        /**
         * 删除历史按钮权限
         */
        roleMenuMapper.delByRoleId(roleDto.getId());
        /**
         * 保存权限对应的按钮权限
         */
        addRoleMenu(roleDto.getMenuList(), roleDto.getId());

        return success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult roleDelete(Long id) {
        if (id == null) {
            return fail(ResultEnum.MUST_PARAMETER);
        }
        if (id.equals(1L) || id.equals(2L)) {
            return fail("该角色不允许删除！");
        }
        sysRoleMapper.deleteByPrimaryKey(id);
        roleMenuMapper.delByRoleId(id);
        return success();
    }

    @Override
    public ResponseResult<RoleMenuDto> roleMenuDetail(Long id) {
        if (id == null) {
            return fail(ResultEnum.MUST_PARAMETER);
        }
        RoleMenuDto roleDto = new RoleMenuDto();
        // 查询角色
        SysRole role = sysRoleMapper.selectByPrimaryKey(id);
        if (ObjectUtils.isEmpty(role)) {
            return fail();
        }
        BeanUtils.copyProperties(role, roleDto);
        List<SysMenuTreeDto> sysMenuTreeDtoList = new ArrayList<>();
        if (id.equals("1")) {
            sysMenuTreeDtoList = treeAllMenu(sysMenuTreeDtoList);

        } else {
            // 查询菜单树
            sysMenuTreeDtoList = treeRoleMenu(sysMenuTreeDtoList, id);
        }
        roleDto.setList(sysMenuTreeDtoList);

        return success(roleDto);
    }

    @Override
    public ResponseResult<SysRole> roleDetail(Long id) {
        if (id == null) {
            return fail(ResultEnum.MUST_PARAMETER);
        }
        // 查询角色
        SysRole role = sysRoleMapper.selectByPrimaryKey(id);

        return success(role);
    }


    @Override
    public ResponseResult<PageBean<SysRole>> roleFind(RoleListDto dto) {
        PageHelper.startPage(dto.getPage(), dto.getRows());
        Page<SysRole> list = (Page<SysRole>) sysRoleMapper.listRole(dto.getRoleName());
        list.getResult().stream().forEach(
                sysRole -> {
                    Integer integer = sysUserMapper.countByRoleId(sysRole.getId());
                    sysRole.setRoleNum(integer);
                }
        );
        return success(list);
    }


    @Override
    public ResponseResult<List<SysMenuTreeDto>> menuAll() {

        List<SysMenuTreeDto> sysMenuTreeDtoList = new ArrayList<>();
        sysMenuTreeDtoList = treeAllMenu(sysMenuTreeDtoList);
        return success(sysMenuTreeDtoList);
    }

    @Override
    public ResponseResult roleAll(BaseAllDto dto) {
        List<SysRole> Roles = sysRoleMapper.listRole(null);
        return success(Roles);
    }

    @Override
    public ResponseResult roleAllNotDefault(BaseAllDto dto) {
        List<SysRole> Roles = sysRoleMapper.listRoleNotDefault();
        return success(Roles);
    }


    @Override
    public ResponseResult<List<SysMenuTreeDto>> myMenuOperation(BaseAllDto baseSysDto) {

        List<SysMenuTreeDto> sysMenuTreeDtoList = new ArrayList<>();

        SysRole role = sysRoleMapper.selectByPrimaryKey(baseSysDto.getLoginRoleId());
        if (ObjectUtils.isEmpty(role)) {
            return success(sysMenuTreeDtoList);
        }
        if (baseSysDto.getLoginIsManage().equals(YesNoEnum.YES.getCode())) {
            sysMenuTreeDtoList = treeAllMenu(sysMenuTreeDtoList);
        } else {

            sysMenuTreeDtoList = treeMyRoleMenu(sysMenuTreeDtoList, baseSysDto.getLoginRoleId());

        }
        return success(sysMenuTreeDtoList);
    }




    @Override
    public ResponseResult<List<SysMenuTreeDto>> myMenu(BaseAllDto baseSysDto) {


        List<SysMenuTreeDto> sysMenuTreeDtoList = new ArrayList<>();

        if (baseSysDto.getLoginIsManage().equals(YesNoEnum.YES.getCode())) {
            sysMenuTreeDtoList = treeAllMenu(sysMenuTreeDtoList);
        } else {

            sysMenuTreeDtoList = treeMyRoleMenu(sysMenuTreeDtoList, baseSysDto.getLoginRoleId());

        }

        return success(sysMenuTreeDtoList);
    }

    @Override
    public ResponseResult<List<SysOperationDto>> myOperation(AllUserMenuDto dto) {
        List<SysOperationDto> sysOperationList = roleMenuMapper.listOperationByRoleIdsAndMenuId(dto.getLoginRoleId(), dto.getMenuId());
        return success(sysOperationList);
    }

    @Override
    public ResponseResult upOrDownRole(AllRoleUpRequest RoleUpRequest) {

        SysRole role = new SysRole();
        role.setState(RoleUpRequest.getStatus());
        role.setId(RoleUpRequest.getId());
        sysRoleMapper.updateByPrimaryKeySelective(role);
        return success();
    }

    @Override
    public ResponseResult<List<SysMenuTreeDto>> myMenuAndBtn(BaseAllDto baseSysDto) {


        List<SysMenuTreeDto> sysMenuTreeDtoList = new ArrayList<>();

        SysRole role = sysRoleMapper.selectByPrimaryKey(baseSysDto.getLoginRoleId());
        if (ObjectUtils.isEmpty(role)) {
            return success(sysMenuTreeDtoList);
        }
        if (role.getId().equals(1L)) {
            sysMenuTreeDtoList = wtMenuMapper.treeAllMenu();
        } else {

            sysMenuTreeDtoList = wtMenuMapper.listAllByRoleId(baseSysDto.getLoginRoleId());


        }
        return success(sysMenuTreeDtoList);

    }




    private List<SysMenuTreeDto> treeRoleMenu(List<SysMenuTreeDto> sysMenuTreeDtoList, Long roleId) {
        if (ObjectUtils.isEmpty(sysMenuTreeDtoList)) {
            sysMenuTreeDtoList = roleMenuMapper.listMenuByRoleId(roleId, 1, null);
        }
        sysMenuTreeDtoList.forEach(
                sysMenuTreeDto -> {
                    List<SysMenuTreeDto> sysMenuTreeDtoList1 = roleMenuMapper.listMenuByRoleId(roleId, null, sysMenuTreeDto.getId());
                    // 根据角色和菜单id查询按钮
                    sysMenuTreeDto.setMenuList(sysMenuTreeDtoList1);
                    if (ObjectUtils.isNotEmpty(sysMenuTreeDtoList1)) {
                        treeRoleMenu(sysMenuTreeDtoList1, roleId);
                    }

                }
        );
        return sysMenuTreeDtoList;
    }

    private List<SysMenuTreeDto> treeBlocRoleMenu(List<SysMenuTreeDto> sysMenuTreeDtoList, Long roleId) {
        if (ObjectUtils.isEmpty(sysMenuTreeDtoList)) {
            sysMenuTreeDtoList = roleMenuMapper.listMenuByRoleId(roleId, 1, null);
            if (CollectionUtils.isEmpty(sysMenuTreeDtoList)) {

                sysMenuTreeDtoList = roleMenuMapper.listBlocMenuByRoleId(2L, 1, null);
            } else {
                return treeRoleMenu(sysMenuTreeDtoList, roleId);
            }
        }

        sysMenuTreeDtoList.forEach(
                sysMenuTreeDto -> {
                    List<SysMenuTreeDto> sysMenuTreeDtoList1 = roleMenuMapper.listBlocMenuByRoleId(2L, null, sysMenuTreeDto.getId());
                    // 根据角色和菜单id查询按钮
                    sysMenuTreeDto.setMenuList(sysMenuTreeDtoList1);
                    if (ObjectUtils.isNotEmpty(sysMenuTreeDtoList1)) {
                        treeBlocRoleMenu(sysMenuTreeDtoList1, 2L);
                    }

                }
        );
        return sysMenuTreeDtoList;
    }


    private List<SysMenuTreeDto> treeAllMenu(List<SysMenuTreeDto> sysMenuTreeDtoList) {
        if (ObjectUtils.isEmpty(sysMenuTreeDtoList)) {
            sysMenuTreeDtoList = wtMenuMapper.listAll(1, null);

        }
        sysMenuTreeDtoList.forEach(
                sysMenuTreeDto -> {
                    List<SysMenuTreeDto> sysMenuTreeDtoList1 = wtMenuMapper.listAll(null, sysMenuTreeDto.getId());
                    sysMenuTreeDto.setFullControl(1);
                    sysMenuTreeDto.setState(1);
                    sysMenuTreeDto.setMenuList(sysMenuTreeDtoList1);
                    if (ObjectUtils.isNotEmpty(sysMenuTreeDtoList1)) {
                        treeAllMenu(sysMenuTreeDtoList1);
                    }

                }
        );
        return sysMenuTreeDtoList;
    }

    private List<SysMenuTreeDto> treeMyRoleMenu(List<SysMenuTreeDto> sysMenuTreeDtoList, Long roleId) {
        if (ObjectUtils.isEmpty(sysMenuTreeDtoList)) {
            sysMenuTreeDtoList = roleMenuMapper.listMenuByRoleIds(roleId, 1, null);

        }
        sysMenuTreeDtoList.forEach(
                sysMenuTreeDto -> {
                    List<SysMenuTreeDto> sysMenuTreeDtoList1 = roleMenuMapper.listMenuByRoleIds(roleId, null, sysMenuTreeDto.getId());

                    sysMenuTreeDto.setMenuList(sysMenuTreeDtoList1);
                    if (ObjectUtils.isNotEmpty(sysMenuTreeDtoList1)) {
                        treeMyRoleMenu(sysMenuTreeDtoList1, roleId);
                    }

                }
        );
        return sysMenuTreeDtoList;
    }



    private List<SysMenuTreeDto> treeMyRoleMenu(List<SysMenuTreeDto> sysMenuTreeDtoList, Long loginRoleId, Long roleId) {
        if (ObjectUtils.isEmpty(sysMenuTreeDtoList)) {
            sysMenuTreeDtoList = roleMenuMapper.listMenuByRoleIds(loginRoleId, 1, null);

        }
        sysMenuTreeDtoList.forEach(
                sysMenuTreeDto -> {
                    List<SysMenuTreeDto> sysMenuTreeDtoList1 = roleMenuMapper.listMenuByRoleIds(loginRoleId, null, sysMenuTreeDto.getId());
                    List<SysOperationDto> operationList = roleMenuMapper.listOperationByRoleIdsAndMenuId(loginRoleId, sysMenuTreeDto.getId());
                    operationList.stream().forEach(
                            sysOperationDto -> {
                                SysRoleMenu RoleMenu1 = roleMenuMapper.selectByRoleIdAndMenuId(sysOperationDto.getId(), roleId, 1);
                                if (!ObjectUtils.isEmpty(RoleMenu1)) {
                                    sysOperationDto.setState(RoleMenu1.getState());
                                } else {
                                    sysOperationDto.setState(0);
                                }
                            }
                    );

                    SysRoleMenu RoleMenu = roleMenuMapper.selectByRoleIdAndMenuId(sysMenuTreeDto.getId(), roleId, 0);
                    if (!ObjectUtils.isEmpty(RoleMenu)) {
                        sysMenuTreeDto.setState(RoleMenu.getState());
                    } else {
                        sysMenuTreeDto.setState(0);
                    }
                    sysMenuTreeDto.setMenuList(sysMenuTreeDtoList1);
                    if (ObjectUtils.isNotEmpty(sysMenuTreeDtoList1)) {
                        treeMyRoleMenu(sysMenuTreeDtoList1, loginRoleId, roleId);
                    }

                }
        );
        return sysMenuTreeDtoList;
    }


    private List<SysMenuTreeDto> treeMyRoleMenu1(List<SysMenuTreeDto> sysMenuTreeDtoList, Long roleId) {
        if (ObjectUtils.isEmpty(sysMenuTreeDtoList)) {
            sysMenuTreeDtoList = roleMenuMapper.listMenuByRoleIds1(roleId, 1, null);

        }
        sysMenuTreeDtoList.forEach(
                sysMenuTreeDto -> {
                    List<SysMenuTreeDto> sysMenuTreeDtoList1 = roleMenuMapper.listMenuByRoleIds1(roleId, null, sysMenuTreeDto.getId());
                    sysMenuTreeDto.setMenuList(sysMenuTreeDtoList1);
                    if (ObjectUtils.isNotEmpty(sysMenuTreeDtoList1)) {
                        treeMyRoleMenu1(sysMenuTreeDtoList1, roleId);
                    }

                }
        );
        return sysMenuTreeDtoList;
    }
}
